namespace DotNetNuke.Services.Scheduling.DNNScheduling
{
    using DotNetNuke.Services.Exceptions;
    using DotNetNuke.Services.Scheduling;
    
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Runtime.CompilerServices;
    using System.Threading;

    public class ProcessGroup
    {
        private static List<WeakReference> __ENCList = new List<WeakReference>();
        private static int numberOfProcesses = 0;
        private static int numberOfProcessesInQueue = 0;
        private static int processesCompleted;
        private static int ticksElapsed;

        public event CompletedEventHandler Completed;

       
        public ProcessGroup()
        {
            List<WeakReference> list = __ENCList;
            lock (list)
            {
                __ENCList.Add(new WeakReference(this));
            }
        }

        public void AddQueueUserWorkItem(ScheduleItem s)
        {
            numberOfProcessesInQueue++;
            numberOfProcesses++;
            ScheduleHistoryItem obj = new ScheduleHistoryItem();
            obj.TypeFullName = s.TypeFullName;
            obj.ScheduleID = s.ScheduleID;
            obj.TimeLapse = s.TimeLapse;
            obj.TimeLapseMeasurement = s.TimeLapseMeasurement;
            obj.RetryTimeLapse = s.RetryTimeLapse;
            obj.RetryTimeLapseMeasurement = s.RetryTimeLapseMeasurement;
            obj.ObjectDependencies = s.ObjectDependencies;
            obj.CatchUpEnabled = s.CatchUpEnabled;
            obj.Enabled = s.Enabled;
            obj.NextStart = s.NextStart;
            obj.ScheduleSource = s.ScheduleSource;
            obj.ThreadID = s.ThreadID;
            obj.ProcessGroup = s.ProcessGroup;
            obj.RetainHistoryNum = s.RetainHistoryNum;
            try
            {
                WaitCallback callback = new WaitCallback(this.RunPooledThread);
                ThreadPool.QueueUserWorkItem(callback, obj);
                Thread.Sleep(0x3e8);
            }
            catch (Exception exception1)
            {

                Exception exc = exception1;
                DotNetNuke.Services.Exceptions.Exceptions.ProcessSchedulerException(exc);

            }
        }

        private SchedulerClient GetSchedulerClient(string strProcess, ScheduleHistoryItem objScheduleHistoryItem)
        {
            Type t = Type.GetType(strProcess, true);
            ScheduleHistoryItem[] param = new ScheduleHistoryItem[] { objScheduleHistoryItem };
            Type[] types = new Type[] { typeof(ScheduleHistoryItem) };
            return (SchedulerClient) t.GetConstructor(types).Invoke(param);
        }

        public void Run(ScheduleHistoryItem objScheduleHistoryItem)
        {
            SchedulerClient Process = null;
            try
            {
                ticksElapsed = Environment.TickCount - ticksElapsed;
                Process = this.GetSchedulerClient(objScheduleHistoryItem.TypeFullName, objScheduleHistoryItem);
                Process.ScheduleHistoryItem = objScheduleHistoryItem;
                Process.ProcessStarted += new WorkStarted(Scheduler.CoreScheduler.WorkStarted);
                Process.ProcessProgressing += new WorkProgressing(Scheduler.CoreScheduler.WorkProgressing);
                Process.ProcessCompleted += new WorkCompleted(Scheduler.CoreScheduler.WorkCompleted);
                Process.ProcessErrored += new WorkErrored(Scheduler.CoreScheduler.WorkErrored);
                Process.Started();
                try
                {
                    Process.ScheduleHistoryItem.Succeeded = false;
                    Process.DoWork();
                }
                catch (Exception exception1)
                {
    
                    Exception exc = exception1;
                    Process.ScheduleHistoryItem.Succeeded = false;
                    Process.Errored(ref exc);
    
                }
                if (Process.ScheduleHistoryItem.Succeeded)
                {
                    Process.Completed();
                }
                if ((processesCompleted == numberOfProcesses) && (processesCompleted == numberOfProcesses))
                {
                    ticksElapsed = Environment.TickCount - ticksElapsed;
                    CompletedEventHandler refObjectHelperS0 = this.Completed;
                    if (refObjectHelperS0 != null)
                    {
                        refObjectHelperS0();
                    }
                }
            }
            catch (Exception exception2)
            {
                
                Exception exc = exception2;
                Process.ScheduleHistoryItem.Succeeded = false;
                Process.Errored(ref exc);

            }
            finally
            {
                numberOfProcessesInQueue--;
                processesCompleted++;
            }
        }

        private void RunPooledThread(object objScheduleHistoryItem)
        {
            this.Run((ScheduleHistoryItem) objScheduleHistoryItem);
        }

        public void RunSingleTask(ScheduleItem s)
        {
            numberOfProcessesInQueue++;
            numberOfProcesses++;
            ScheduleHistoryItem obj = new ScheduleHistoryItem();
            obj.TypeFullName = s.TypeFullName;
            obj.ScheduleID = s.ScheduleID;
            obj.TimeLapse = s.TimeLapse;
            obj.TimeLapseMeasurement = s.TimeLapseMeasurement;
            obj.RetryTimeLapse = s.RetryTimeLapse;
            obj.RetryTimeLapseMeasurement = s.RetryTimeLapseMeasurement;
            obj.ObjectDependencies = s.ObjectDependencies;
            obj.CatchUpEnabled = s.CatchUpEnabled;
            obj.Enabled = s.Enabled;
            obj.NextStart = s.NextStart;
            obj.ScheduleSource = s.ScheduleSource;
            obj.ThreadID = s.ThreadID;
            obj.ProcessGroup = s.ProcessGroup;
            try
            {
                this.Run(obj);
                Thread.Sleep(0x3e8);
            }
            catch (Exception exception1)
            {

                Exception exc = exception1;
                DotNetNuke.Services.Exceptions.Exceptions.ProcessSchedulerException(exc);

            }
        }

        public static int GetProcessesCompleted
        {
            get
            {
                return processesCompleted;
            }
        }

        public static int GetProcessesInQueue
        {
            get
            {
                return numberOfProcessesInQueue;
            }
        }

        public static int GetTicksElapsed
        {
            get
            {
                return ticksElapsed;
            }
        }

        public delegate void CompletedEventHandler();
    }
}

